package com.haohan.cloud.scm.goods.core.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.haohan.cloud.scm.api.common.tree.TreeUtil;
import com.haohan.cloud.scm.api.constant.enums.goods.ModelAttrNameEnum;
import com.haohan.cloud.scm.api.goods.dto.GoodsCategoryDTO;
import com.haohan.cloud.scm.api.goods.dto.GoodsDTO;
import com.haohan.cloud.scm.api.goods.dto.GoodsModelDTO;
import com.haohan.cloud.scm.api.goods.dto.imp.GoodsCategoryImport;
import com.haohan.cloud.scm.api.goods.dto.imp.GoodsImport;
import com.haohan.cloud.scm.api.goods.entity.Goods;
import com.haohan.cloud.scm.api.goods.entity.GoodsCategory;
import com.haohan.cloud.scm.api.goods.trans.GoodsTrans;
import com.haohan.cloud.scm.api.manage.entity.Shop;
import com.haohan.cloud.scm.common.tools.util.ValidatorUtil;
import com.haohan.cloud.scm.goods.core.GoodsImportInfoCoreService;
import com.haohan.cloud.scm.goods.service.GoodsCategoryService;
import com.haohan.cloud.scm.goods.service.GoodsService;
import com.haohan.cloud.scm.goods.utils.ScmGoodsUtils;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author dy
 * @date 2019/10/16
 */
@Service
@AllArgsConstructor
public class GoodsImportInfoCoreServiceImpl implements GoodsImportInfoCoreService {

    private final GoodsCategoryService goodsCategoryService;
    private final GoodsService goodsService;
    private final GoodsCoreBaseService goodsCoreBaseService;
    private final ScmGoodsUtils scmGoodsUtils;

    /**
     * 商品分类导入
     *
     * @param categoryList
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String categoryImport(List<GoodsCategoryImport> categoryList, String shopId) {
        StringBuilder msg = new StringBuilder();
        // 店铺验证
        Shop shop = scmGoodsUtils.fetchShopById(shopId);
        if (null == shop) {
            msg.append("当前店铺设置有误。");
            return msg.toString();
        }
        String merchantId = shop.getMerchantId();

        int index = 0;
        int errorNum = 0;
        int successNum = 0;
        int size = categoryList.size() * 4 / 3 + 1;
        size = Math.max(8, size);
        List<GoodsCategoryDTO> saveList = new ArrayList<>(size);
        // key:商品分类名称
        Map<String, GoodsCategoryDTO> categoryMap = new HashMap<>(size);
        // 先验证必填项是否正确
        for (GoodsCategoryImport rowInfo : categoryList) {
            index++;
            // 行数据校验
            if (ValidatorUtil.validateInfo(rowInfo, index, msg)) {
                errorNum++;
                continue;
            }
            GoodsCategoryDTO category = rowInfo.transTo();
            if (categoryMap.containsKey(category.getName())) {
                msg.append("第").append(index).append("行填写有误: 商品分类名称重复|");
                errorNum++;
                continue;
            }
            // 商家店铺
            category.setShopId(shopId);
            category.setMerchantId(merchantId);
            categoryMap.put(category.getName(), category);
            saveList.add(category);
        }
        if (errorNum == 0) {
            index = 0;
            for (GoodsCategoryDTO category : saveList) {
                index++;
                // 验证是否重名，处理商品分类及上级商品分类
                if (goodsCategoryHandler(category, categoryMap, index, msg)) {
                    errorNum++;
                    continue;
                }
                successNum++;
            }
        }
        // 保存
        if (errorNum == 0) {
            // 先保存父级
            saveList.forEach(goodsCoreBaseService::saveCategoryFirstParent);
            msg.insert(0, "导入成功，本次共导入商品分类信息" + successNum + "条记录。|");
        } else {
            msg.insert(0, "导入失败，请更正后重新导入。|");
        }
        return msg.toString();
    }

    /**
     * 验证是否重名，处理商品分类及上级商品分类
     *
     * @param category
     * @param categoryMap
     * @param index
     * @param msg
     * @return
     */
    private boolean goodsCategoryHandler(GoodsCategoryDTO category, Map<String, GoodsCategoryDTO> categoryMap, int index, StringBuilder msg) {
        GoodsCategory exist = goodsCategoryService.fetchByName(category.getShopId(), category.getName());
        if (null != exist) {
            msg.append("第").append(index).append("行填写有误: 该商品分类已存在|");
            return true;
        }
        // 父级设置
        GoodsCategoryDTO parent;
        String parentName = category.getParentName();
        if (StrUtil.equals(TreeUtil.ROOT_NAME, parentName) || StrUtil.equals(category.getName(), parentName)) {
            // 父级名称和分类名称相同时设置为根节点
            category.setParentName(TreeUtil.ROOT_NAME);
            category.setParentNameAll(StrUtil.format(",{},", TreeUtil.ROOT_NAME));
            category.setParentCategory(null);
            return false;
        } else if (categoryMap.containsKey(parentName)) {
            parent = categoryMap.get(parentName);
            category.setParentNameAll(StrUtil.format(",{},{},", parent.getParentName(), parentName));
        } else {
            // 查询已有
            GoodsCategory existParent = goodsCategoryService.fetchByName(category.getShopId(), parentName);
            if (null != existParent) {
                // 已有分类的所有父级处理
                String parentNameAll = goodsCategoryService.fetchParentList(existParent.getId()).stream().map(GoodsCategory::getName).collect(Collectors.joining(StrUtil.COMMA));
                parent = new GoodsCategoryDTO(existParent);
                parent.setParentNameAll(StrUtil.format(",{},{},", TreeUtil.ROOT_NAME, parentNameAll));
                categoryMap.put(parentName, parent);
                category.setParentNameAll(StrUtil.format("{}{},", parent.getParentNameAll(), parentName));
            } else {
                msg.append("第").append(index).append("行填写有误: 找不到对应上级分类|");
                return true;
            }
        }
        // 父级循环验证：父级名称列表中不能包含自己名称
        if (category.getParentNameAll().contains(StrUtil.format(",{},", category.getName()))) {
            msg.append("第").append(index).append("行填写有误: 该分类的上级分类中包含自己|");
            return true;
        }
        category.setParentCategory(parent);
        return false;
    }


    /**
     * 零售商品导入
     *
     * @param goodsList
     * @param shopId
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String goodsImport(List<GoodsImport> goodsList, String shopId) {
        StringBuilder msg = new StringBuilder();
        // 店铺验证
        Shop shop = scmGoodsUtils.fetchShopById(shopId);
        if (null == shop) {
            msg.append("当前店铺设置有误。");
            return msg.toString();
        }

        int index = 0;
        int errorNum = 0;
        int successNum = 0;
        int size = Math.max(8, goodsList.size() * 4 / 3 + 1);
        // key:goodsName
        Map<String, GoodsDTO> goodsMap = new HashMap<>(size);
        // goodsName + modelInfo
        Set<String> modelSet = new HashSet<>(size);
        // 商品分类  categoryId:name
        Map<String, String> categoryMap = new HashMap<>(size);

        for (GoodsImport rowInfo : goodsList) {
            index++;
            // 行数据处理
            if (goodsHandle(rowInfo, index, msg, goodsMap, modelSet, categoryMap, shop)) {
                errorNum++;
                continue;
            }
            successNum++;
        }
        // 保存
        if (errorNum == 0) {
            goodsMap.values().forEach(goodsCoreBaseService::saveGoodsWithDetail);
            msg.insert(0, "导入成功，本次共导入商品" + goodsMap.size() + "种, 商品规格信息" + successNum + "条记录。|");
        } else {
            msg.insert(0, "导入失败，请更正后重新导入。|");
        }
        return msg.toString();
    }

    /**
     * 商品及规格验证 设置
     *
     * @return
     */
    private boolean goodsHandle(GoodsImport rowInfo, int index, StringBuilder msg, Map<String, GoodsDTO> goodsMap, Set<String> modelSet, Map<String, String> categoryMap, Shop shop) {
        // 行数据校验
        if (ValidatorUtil.validateInfo(rowInfo, index, msg)) {
            return true;
        }
        // 规格名称处理  属性名：属性值
        Map<ModelAttrNameEnum, String> modelInfoMap = GoodsTrans.fetchModelInfoMap(rowInfo.getModelInfo());
        if (modelInfoMap.isEmpty()) {
            msg.append("第").append(index).append("行填写有误: 规格属性信息有误;|");
            return true;
        }
        String modelName = CollUtil.join(modelInfoMap.values(), ",");
        String modelInfo = GoodsTrans.transToModelInfo(modelInfoMap);
        rowInfo.setModelInfo(modelInfo);

        String goodsName = rowInfo.getGoodsName();
        String setValue = goodsName.concat(modelInfo);
        if (modelSet.contains(setValue)) {
            msg.append("第").append(index).append("行填写有误: 规格属性信息(").append(modelInfo).append(")重复;|");
            return true;
        }
        modelSet.add(setValue);

        // 库存初始值1000
        if (null == rowInfo.getStorage()) {
            rowInfo.setStorage(new BigDecimal(1000));
        }
        String shopId = shop.getId();
        // 查找商品, 已有商品不可新增
        GoodsDTO goods;
        if (goodsMap.containsKey(goodsName)) {
            goods = goodsMap.get(goodsName);
        } else {
            Goods exist = goodsService.fetchByName(shopId, goodsName);
            if (null != exist) {
                msg.append("第").append(index).append("行填写有误: 该商品已存在;|");
                return true;
            }
            // 商品分类
            String categoryName = rowInfo.getCategoryName();
            String categoryId = categoryMap.get(categoryName);
            if (null == categoryId) {
                GoodsCategory category = goodsCategoryService.fetchByName(shopId, categoryName);
                if (null == category) {
                    msg.append("第").append(index).append("行填写有误: 该商品分类不存在;|");
                    return true;
                }
                categoryId = category.getId();
                categoryMap.put(categoryName, categoryId);
            }

            // 添加商品属性
            goods = rowInfo.initGoods();
            goods.setShopId(shopId);
            goods.setMerchantId(shop.getMerchantId());
            goods.setCategoryId(categoryId);
            goodsMap.put(goodsName, goods);
        }
        // 添加规格属性
        GoodsModelDTO model = rowInfo.initGoodsModel();
        model.setModelName(modelName);
        model.setModelInfoMap(modelInfoMap);
        goods.getModelList().add(model);
        // 规格名称添加
        Map<ModelAttrNameEnum, List<String>> attrMap = goods.getAttrMap();
        modelInfoMap.forEach((key, value) -> {
            if (attrMap.containsKey(key)) {
                attrMap.get(key).add(value);
            } else {
                List<String> list = new ArrayList<>(8);
                list.add(value);
                attrMap.put(key, list);
            }
        });
        return false;
    }


}
